package com.fenxiao.kindeditor.action;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.struts2.ServletActionContext;


import com.fenxiao.kindeditor.util.DateUtil;
import com.fenxiao.kindeditor.util.KindEditorUploadFile;
import com.fenxiao.kindeditor.util.KindEditorUtil;
import com.fenxiao.util.PromptMessage;
import com.fenxiao.util.Tools;
import com.opensymphony.xwork2.ActionSupport;


/**
 * 
 * KindEditor Action
 * 
 * @author ChenYong
 *
 */
public class KindEditorAction extends ActionSupport {
	// Field
	// 版本号
	private static final long serialVersionUID = 7462357740709561285L;
	// 上传文件
	private File imgFile;
	// 上传文件名称
	private String imgFileFileName;
	// 上传文件类型
	private String imgFileContentType;
	// 上传文件保存路径
	private String savePath;
	// 上传文件保存 url
	private String saveUrl;
	// 提示信息
	private PromptMessage promptMessage;
	// KindEditor 上传的文件信息
	private KindEditorUploadFile kindEditorUploadFile;
	// ---------- KindEditor 浏览远程文件的请求参数 Start ----------//
	// 路径
	private String path;
	// 排序方式
	private String order;
	// 目录
	private String dir;
	// ---------- KindEditor 浏览远程文件的请求参数 End ----------//
	// 图文信息
	private String content;

	// 普通初始化块
	{
		promptMessage = new PromptMessage();
		kindEditorUploadFile = new KindEditorUploadFile();

		// 默认设置
		promptMessage.setError(1);
		promptMessage.setMessage("只能上传图片, 且大小不超过 2MB!");
	}

	// Getters and Setters
	public File getImgFile() {
		return imgFile;
	}

	public void setImgFile(File imgFile) {
		this.imgFile = imgFile;
	}

	public String getImgFileFileName() {
		return imgFileFileName;
	}

	public void setImgFileFileName(String imgFileFileName) {
		this.imgFileFileName = imgFileFileName;
	}

	public String getImgFileContentType() {
		return imgFileContentType;
	}

	public void setImgFileContentType(String imgFileContentType) {
		this.imgFileContentType = imgFileContentType;
	}

	public String getSavePath() {
		return ServletActionContext.getRequest().getSession().getServletContext().getRealPath(savePath);
	}

	public void setSavePath(String savePath) {
		this.savePath = savePath;
	}

	public String getSaveUrl() {
		saveUrl = ServletActionContext.getRequest().getContextPath() + savePath;

		return saveUrl;
	}

	public void setSaveUrl(String saveUrl) {
		this.saveUrl = saveUrl;
	}

	public PromptMessage getPromptMessage() {
		return promptMessage;
	}

	public void setPromptMessage(PromptMessage promptMessage) {
		this.promptMessage = promptMessage;
	}

	public KindEditorUploadFile getKindEditorUploadFile() {
		return kindEditorUploadFile;
	}

	public void setKindEditorUploadFile(KindEditorUploadFile kindEditorUploadFile) {
		this.kindEditorUploadFile = kindEditorUploadFile;
	}

	public String getPath() {
		return path;
	}

	public void setPath(String path) {
		this.path = path;
	}

	public String getOrder() {
		return order.toLowerCase();
	}

	public void setOrder(String order) {
		this.order = order;
	}

	public String getDir() {
		return dir;
	}

	public void setDir(String dir) {
		this.dir = dir;
	}

	public String getContent() {
		return content;
	}

	public void setContent(String content) {
		this.content = content;
	}

	// Action mehtod
	/**
	 * 
	 * 文件上传处理方法
	 * 
	 * @return "input"
	 * 
	 */
	public String upload() {
		// 输入流
		InputStream is = null;
		// 输出流
		OutputStream os = null;

		try {
			// 文件名称
			String fileName = KindEditorUtil.getNewFileName(imgFileFileName);

			// 如果是图片
			if (KindEditorUtil.getImageType().contains(KindEditorUtil.getExtensionName(fileName))) {
				// 用当天日期作为目录名称
				String dirName = DateUtil.format(new Date(), "yyyyMMdd");
				File dir = new File(getSavePath() + File.separator + KindEditorUtil.getDirName().get(2) + File.separator + dirName);
				
				if (!dir.exists()) {
					dir.mkdir();
				}
				
				is = new FileInputStream(imgFile);
				os = new FileOutputStream(getSavePath() + File.separator + KindEditorUtil.getDirName().get(2) + File.separator + dirName + File.separator + fileName);
				
				// 字节缓冲区
				byte[] buffer = new byte[1024];
				// 读取的字节数
				int length = 0;

				// 将输入流写入输出流指定的文件中
				while ((length = is.read(buffer)) > 0) {
					os.write(buffer, 0, length);
				}

				promptMessage.setError(0);
				promptMessage.setMessage("");
				promptMessage.setUrl(getSaveUrl() + "/" + KindEditorUtil.getDirName().get(2) + "/" + dirName + "/" + fileName);
			}
		} catch (Exception e) {
			promptMessage.setMessage("很遗憾，上传失败！");
		} finally {
			// 关闭流
			try {
				if (is != null) {
					is.close();
				}

				if (os != null) {
					os.close();
				}
			} catch (Exception e) {
			}
		}

		return INPUT;
	}

	/**
	 * 
	 * 获取上传文件
	 * 
	 * @return "download"
	 * 
	 */
	public String download() {
		try {
			// 上传目录的绝对路径
			StringBuffer uploadDirName = new StringBuffer();
			
			if (path != null && !"null".equals(path) && !"".equals(path)) {
				uploadDirName.append(path);
				
				// 从 path 中截取目录名称
				if ((path.lastIndexOf("\\") + 1) < path.length()) {
					String dirName4Path = path.substring(path.lastIndexOf("\\") + 1, path.lastIndexOf("/"));
					
					// 访问文件的 Url
					kindEditorUploadFile.setCurrent_url(getSaveUrl() + "/" + getDir() + "/" + dirName4Path + "/");
				} else {
					// 访问文件的 Url
					kindEditorUploadFile.setCurrent_url(getSaveUrl() + "/" + getDir() + "/");
				}
			} else {
				uploadDirName.append(getSavePath());
				uploadDirName.append(File.separator);
				uploadDirName.append(getDir());
				uploadDirName.append(File.separator);
				
				// 访问文件的 Url
				kindEditorUploadFile.setCurrent_url(getSaveUrl() + "/" + getDir() + "/");
			}
			
			// 上传目录
			File uploadDir = new File(uploadDirName.toString());
			// 上传目录中的文件信息
			List<Map<String, Object>> fileList = new ArrayList<Map<String, Object>>();

			// 如果上传目录中有文件
			if (uploadDir.listFiles() != null) {
				// 遍历上传目录
				for (File file : uploadDir.listFiles()) {
					Map<String, Object> map = new HashMap<String, Object>();
					String fileName = file.getName();
					
					// 如果 file 是一个目录
					if (file.isDirectory()) {
						map.put("is_dir", true);
						map.put("has_file", (file.listFiles() != null));
						map.put("filesize", ((file.listFiles() != null) ? (file.listFiles().length) : 0L));
						map.put("is_photo", false);
						map.put("filetype", "");

						// 如果 f 是一个文件
					} else if (file.isFile()) {
						String fileType = KindEditorUtil.getExtensionName(fileName).toLowerCase();

						map.put("is_dir", false);
						map.put("has_file", false);
						map.put("filesize", file.length());
						map.put("is_photo", true);
						map.put("filetype", fileType);
					}

					map.put("filename", fileName);
					map.put("datetime", DateUtil.format(file.lastModified(), "yyyy-MM-dd HH:mm:ss"));

					fileList.add(map);
				}
				
				// 排序
				// 按大小排序
				if ("size".equals(getOrder())) {
					Collections.sort(fileList, new SizeComparator());

					// 按类型排序
				} else if ("type".equals(getOrder())) {
					Collections.sort(fileList, new TypeComparator());

					// 按名称排序
				} else {
					Collections.sort(fileList, new NameComparator());
				}

				// 设置
				// 移到上一级目录的路径
				kindEditorUploadFile.setMoveup_dir_path(getSavePath() + File.separator + getDir() + File.separator);
				// 当前目录的路径
				kindEditorUploadFile.setCurrent_dir_path(uploadDirName.toString());
				// 文件数量
				kindEditorUploadFile.setTotal_count(fileList.size());
				// 文件列表
				kindEditorUploadFile.setFile_list(fileList);
			}
		} catch (Exception e) {
		}

		return "download";
	}

	/**
	 * 
	 * 保存图文信息
	 * 
	 * @return "save"
	 * 
	 */
	public String save() {
		ServletActionContext.getRequest().setAttribute("content", content);

		return SUCCESS;
	}
}

/**
 * 
 * 名称比较器
 * 
 * @author ChenYong
 * 
 */
class NameComparator implements Comparator<Map<String, Object>> {
	public int compare(Map<String, Object> map1, Map<String, Object> map2) {
		// 如果 map1, map2 都是目录, 则按目录名称转换的日期比较
		if (((Boolean) map1.get("is_dir")) && ((Boolean) map2.get("is_dir"))) {
			try {
				Date date1 = DateUtil.parse((String) map1.get("filename"), "yyyyMMdd");
				Date date2 = DateUtil.parse((String) map2.get("filename"), "yyyyMMdd");

				// 如果 date1, date2 相等, 则按目录名称比较
				if (date1.equals(date2)) {
					return ((String) map1.get("filename")).compareTo((String) map2.get("filename"));
				}
					
				return -date1.compareTo(date2);
			} catch (Exception e) {
				return -1;
			}
			
			// 如果 map1 是目录, map2 是文件, 返回 -1
		} else if (((Boolean) map1.get("is_dir")) && !((Boolean) map2.get("is_dir"))) {
			return -1;
			
			// 如果 map1 是文件, map2 是目录, 返回 1
		} else if (!((Boolean) map1.get("is_dir")) && ((Boolean) map2.get("is_dir"))) {
			return 1;
			
			// 如果 map1, map2 都是文件, 则按文件生成的日期比较
		} else {
			Date date1 = DateUtil.parse((String) map1.get("datetime"), "yyyy-MM-dd HH:mm:ss");
			Date date2 = DateUtil.parse((String) map2.get("datetime"), "yyyy-MM-dd HH:mm:ss");

			// 如果 date1, date2 相等, 则按文件名称比较
			if (date1.equals(date2)) {
				return ((String) map1.get("filename")).compareTo((String) map2.get("filename"));
			}
				
			return -date1.compareTo(date2);
		}
	}
}

/**
 * 
 * 大小比较器
 * 
 * @author ChenYong
 * 
 */
class SizeComparator implements Comparator<Map<String, Object>> {
	public int compare(Map<String, Object> map1, Map<String, Object> map2) {
		// 如果 map1, map2 都是目录, 则按目录中文件数量比较
		if (((Boolean) map1.get("is_dir")) && ((Boolean) map2.get("is_dir"))) {
			// 如果 map1, map2 中文件数量相等, 则按目录名称比较
			if (((Long) map1.get("filesize")).equals(((Long) map2.get("filesize")))) {
				return ((String) map1.get("filename")).compareTo((String) map2.get("filename"));
			} 
			
			return ((Long) map1.get("filesize")).compareTo(((Long) map2.get("filesize")));
			
			// 如果 map1 是目录, map2 是文件, 返回 -1
		} else if (((Boolean) map1.get("is_dir")) && !((Boolean) map2.get("is_dir"))) {
			return -1;
				
			// 如果 map1 是文件, map2 是目录, 返回 1
		} else if (!((Boolean) map1.get("is_dir")) && ((Boolean) map2.get("is_dir"))) {
			return 1;
					
			// 如果 map1, map2 都是文件, 则按文件大小比较
		} else {
			// 如果 map1, map2 大小相等, 则按文件名称比较
			if (((Long) map1.get("filesize")).equals(((Long) map2.get("filesize")))) {
				return ((String) map1.get("filename")).compareTo((String) map2.get("filename"));
			}
			
			return ((Long) map1.get("filesize")).compareTo(((Long) map2.get("filesize")));
		}
	}
}

/**
 * 
 * 类型比较器
 * 
 * @author ChenYong
 * 
 */
class TypeComparator implements Comparator<Map<String, Object>> {
	public int compare(Map<String, Object> map1, Map<String, Object> map2) {
		// 如果 map1, map2 都是目录, 则按目录名称转换的日期比较
		if (((Boolean) map1.get("is_dir")) && ((Boolean) map2.get("is_dir"))) {
			try {
				Date date1 = DateUtil.parse((String) map1.get("filename"), "yyyyMMdd");
				Date date2 = DateUtil.parse((String) map2.get("filename"), "yyyyMMdd");

				// 如果 date1, date2 相等, 则按目录名称比较
				if (date1.equals(date2)) {
					return ((String) map1.get("filename")).compareTo((String) map2.get("filename"));
				}
					
				return -date1.compareTo(date2);
			} catch (Exception e) {
				return -1;
			}
			
			// 如果 map1 是目录, map2 是文件, 返回 -1
		} else if (((Boolean) map1.get("is_dir")) && !((Boolean) map2.get("is_dir"))) {
			return -1;
				
			// 如果 map1 是文件, map2 是目录, 返回 1
		} else if (!((Boolean) map1.get("is_dir")) && ((Boolean) map2.get("is_dir"))) {
			return 1;
					
			// 如果 map1, map2 都是文件, 则按文件类型比较
		} else {
			// 如果 map1, map2 类型相同, 则按文件名称比较
			if (((String) map1.get("filetype")).equals((String) map2.get("filetype"))) {
				return ((String) map1.get("filename")).compareTo((String) map2.get("filename"));
			}
			
			return ((String) map1.get("filetype")).compareTo((String) map2.get("filetype"));
		}
	}
}